﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using DDD;
using FloatComparer = UnitTest.TestHelper.FloatComparer;

namespace UnitTest {
    [TestClass]
    public class TestFrameBuffer_Color8_Depth0 {

        #region Field
        GameWindow window;
        World wld;
        Graphics3D g3d;
        FrameBuffer fbuf;
        #endregion

        #region Setup
        [TestInitialize ()]
        public void MyClassInitialize () {
            window = new GameWindow ();
            wld = CreateWorld ();
            fbuf = CreateFrameBuffer ();

            g3d = Graphics3D.GetInstance ();
            g3d.Reset ();

            g3d.RenderPass += delegate {
                g3d.SetFrameBuffer (fbuf);
                g3d.SetWorld (wld);
                g3d.SetViewort (0, 0, 1, 1);
            };
        }

        [TestCleanup ()]
        public void MyClassCleanup () {
            window.Dispose ();
            window = null;
            wld = null;
        }

        private static FrameBuffer CreateFrameBuffer () {
            var fbuf = new FrameBuffer (8, 0, 0);
            var color0 = new Image2D<float> (DDD.PixelFormat.R8, 1, 1);
            var color1 = new Image2D<float> (DDD.PixelFormat.R8, 1, 1);
            var color2 = new Image2D<float> (DDD.PixelFormat.R8, 1, 1);
            var color3 = new Image2D<float> (DDD.PixelFormat.R8, 1, 1);
            var color4 = new Image2D<float> (DDD.PixelFormat.R8, 1, 1);
            var color5 = new Image2D<float> (DDD.PixelFormat.R8, 1, 1);
            var color6 = new Image2D<float> (DDD.PixelFormat.R8, 1, 1);
            var color7 = new Image2D<float> (DDD.PixelFormat.R8, 1, 1);
            fbuf.SetColorBuffer (0, color0);
            fbuf.SetColorBuffer (1, color1);
            fbuf.SetColorBuffer (2, color2);
            fbuf.SetColorBuffer (3, color3);
            fbuf.SetColorBuffer (4, color4);
            fbuf.SetColorBuffer (5, color5);
            fbuf.SetColorBuffer (6, color6);
            fbuf.SetColorBuffer (7, color7);
            return fbuf;
        }


        private World CreateWorld () {
            var cam = new Camera ();
            cam.SetPerspective (45, 1, 0.1f, 10f);

            var camNode = new Node ();
            camNode.Attach (cam);
            camNode.SetTranslation (0, 0, 1);

            var pos = new float[3] { 0, 0, 0 };
            var col0 = new float[1] { 0.0f };
            var col1 = new float[1] { 0.1f };
            var col2 = new float[1] { 0.2f };
            var col3 = new float[1] { 0.3f };
            var col4 = new float[1] { 0.4f };
            var col5 = new float[1] { 0.5f };
            var col6 = new float[1] { 0.6f };
            var col7 = new float[1] { 0.7f };
            var posArray = new VertexArray<float> (1, 3);
            var colArray0 = new VertexArray<float> (1, 1);
            var colArray1 = new VertexArray<float> (1, 1);
            var colArray2 = new VertexArray<float> (1, 1);
            var colArray3 = new VertexArray<float> (1, 1);
            var colArray4 = new VertexArray<float> (1, 1);
            var colArray5 = new VertexArray<float> (1, 1);
            var colArray6 = new VertexArray<float> (1, 1);
            var colArray7 = new VertexArray<float> (1, 1);
            posArray.Set (0, 1, pos);
            colArray0.Set (0, 1, col0);
            colArray1.Set (0, 1, col1);
            colArray2.Set (0, 1, col2);
            colArray3.Set (0, 1, col3);
            colArray4.Set (0, 1, col4);
            colArray5.Set (0, 1, col5);
            colArray6.Set (0, 1, col6);
            colArray7.Set (0, 1, col7);
 
            var vbuf = new VertexBuffer ();
            vbuf.AddVertexArray ("v_Position", posArray);
            vbuf.AddVertexArray ("v_Color0", colArray0);
            vbuf.AddVertexArray ("v_Color1", colArray1);
            vbuf.AddVertexArray ("v_Color2", colArray2);
            vbuf.AddVertexArray ("v_Color3", colArray3);
            vbuf.AddVertexArray ("v_Color4", colArray4);
            vbuf.AddVertexArray ("v_Color5", colArray5);
            vbuf.AddVertexArray ("v_Color6", colArray6);
            vbuf.AddVertexArray ("v_Color7", colArray7);

            var ibuf = new IndexBuffer<int> (PrimitiveType.Point, 1);
            var indices = new int[] { 0, 1 };
            ibuf.Set (0, 1, indices);

            var vert = @"#version 400
                         in  vec3 v_Position;
                         in  float v_Color0;
                         in  float v_Color1;
                         in  float v_Color2;
                         in  float v_Color3;
                         in  float v_Color4;
                         in  float v_Color5;
                         in  float v_Color6;
                         in  float v_Color7;
                         out float f_Color0;
                         out float f_Color1;
                         out float f_Color2;
                         out float f_Color3;
                         out float f_Color4;
                         out float f_Color5;
                         out float f_Color6;
                         out float f_Color7;
                               
                         void main () {
                             gl_Position = vec4(v_Position, 1);
                             f_Color0 = v_Color0;
                             f_Color1 = v_Color1;
                             f_Color2 = v_Color2;
                             f_Color3 = v_Color3;
                             f_Color4 = v_Color4;
                             f_Color5 = v_Color5;
                             f_Color6 = v_Color6;
                             f_Color7 = v_Color7;
                         }
                        ";
            var frag = @"#version 400
                         in  float f_Color0;
                         in  float f_Color1;
                         in  float f_Color2;
                         in  float f_Color3;
                         in  float f_Color4;
                         in  float f_Color5;
                         in  float f_Color6;
                         in  float f_Color7;
                         layout (location = 0) out float frag_Color0;
                         layout (location = 1) out float frag_Color1;
                         layout (location = 2) out float frag_Color2;
                         layout (location = 3) out float frag_Color3;
                         layout (location = 4) out float frag_Color4;
                         layout (location = 5) out float frag_Color5;
                         layout (location = 6) out float frag_Color6;
                         layout (location = 7) out float frag_Color7;
                               
                         void main () {
                             frag_Color0 = f_Color0;
                             frag_Color1 = f_Color1;
                             frag_Color2 = f_Color2;
                             frag_Color3 = f_Color3;
                             frag_Color4 = f_Color4;
                             frag_Color5 = f_Color5;
                             frag_Color6 = f_Color6;
                             frag_Color7 = f_Color7;
                         }
                        ";

            var vs = new VertexShader (new MemoryStream (Encoding.UTF8.GetBytes (vert)));
            var fs = new FragmentShader (new MemoryStream (Encoding.UTF8.GetBytes (frag)));
            var sp = new ShaderProgram (vs, fs);

            var app = new Appearance ();
            app.SetShaderProgram (sp);

            var msh = new Mesh ();
            msh.SetVertexBuffer (vbuf);
            msh.SetIndexBuffer (ibuf);
            msh.SetAppearance (app);

            var mshNode = new Node ();
            mshNode.Attach (msh);

            var wld = new World ();
            wld.AddChild (camNode);
            wld.AddChild (mshNode);
            wld.SetActiveCamera (camNode);

            return wld;
        }

        #endregion



        #region TestMethod
        [TestMethod]
        public void TestMethod1 () {

            g3d.Render ();
            window.SwapBuffers ();

            var colors0 = new float[1];
            var colors1 = new float[1];
            var colors2 = new float[1];
            var colors3 = new float[1];
            var colors4 = new float[1];
            var colors5 = new float[1];
            var colors6 = new float[1];
            var colors7 = new float[1];

            var color0 = fbuf.GetColorBuffer (0) as Image2D<float>;
            var color1 = fbuf.GetColorBuffer (1) as Image2D<float>;
            var color2 = fbuf.GetColorBuffer (2) as Image2D<float>;
            var color3 = fbuf.GetColorBuffer (3) as Image2D<float>;
            var color4 = fbuf.GetColorBuffer (4) as Image2D<float>;
            var color5 = fbuf.GetColorBuffer (5) as Image2D<float>;
            var color6 = fbuf.GetColorBuffer (6) as Image2D<float>;
            var color7 = fbuf.GetColorBuffer (7) as Image2D<float>;
            color0.Capture ();
            color1.Capture ();
            color2.Capture ();
            color3.Capture ();
            color4.Capture ();
            color5.Capture ();
            color6.Capture ();
            color7.Capture ();
            color0.Get (0, 0, 1, 1, colors0);
            color1.Get (0, 0, 1, 1, colors1);
            color2.Get (0, 0, 1, 1, colors2);
            color3.Get (0, 0, 1, 1, colors3);
            color4.Get (0, 0, 1, 1, colors4);
            color5.Get (0, 0, 1, 1, colors5);
            color6.Get (0, 0, 1, 1, colors6);
            color7.Get (0, 0, 1, 1, colors7);

            Assert.AreEqual (0.0, colors0[0], 0.01);
            Assert.AreEqual (0.1, colors1[0], 0.01);
            Assert.AreEqual (0.2, colors2[0], 0.01);
            Assert.AreEqual (0.3, colors3[0], 0.01);
            Assert.AreEqual (0.4, colors4[0], 0.01);
            Assert.AreEqual (0.5, colors5[0], 0.01);
            Assert.AreEqual (0.6, colors6[0], 0.01);
            Assert.AreEqual (0.7, colors7[0], 0.01);
        }
        #endregion
    }


    
}
